import json
from time import sleep

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree


class AcquireSN:
    def __init__(self, url, user, pwd, path):
        self.url = url
        self.user = user
        self.pwd = pwd
        self.path = path
        self.driver = None

        self.sn = {}

    # 登录
    def login(self):
        try:
            options = webdriver.ChromeOptions()
            options.add_argument('ignore-certificate-errors')
            driver = webdriver.Chrome(options=options)
            driver.maximize_window()
            driver.get(self.url)
            # 等待用户名输入框出现
            username_input = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, "login-username"))
            )
            # 填写用户名
            username_input.send_keys(self.user)
            # 填写密码
            password_input = driver.find_element(By.ID, "login-password")
            password_input.send_keys(self.pwd)
            # 点击登录按钮
            sleep(3)
            login_button = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.XPATH, "//button"))
            )
            login_button.click()
            sleep(5)
            # 将登陆后的driver返回
            self.driver = driver
        except Exception as e:
            print(e)

    # 获取服务器SN号
    def get_server_sn(self):
        # self.driver.switch_to.window(self.driver.window_handles[-1])
        # 等待页面加载
        server_sn = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.ID, "summaryBlock"))
        )
        server_sn = self.driver.find_element(By.XPATH, "//*[@id='serialNumber']").text
        self.sn = {
            "服务器型号": "H3C UniServer R4900 G5",
            "快速服务代码": "",
            "服务器SN号": server_sn
        }

    # 获取内存条SN号
    def get_mem_sn(self):
        cpu1_mem = {}
        cpu2_mem = {}
        # 进入系统管理
        system_management = self.driver.find_element(By.XPATH, "//div[@class='framework-nav']//h1[2]")
        system_management.click()
        # 进入内存详情页
        mem = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//*[@id='app-tab']//li[3]"))
        )
        mem.click()
        # 滑倒底部
        # mem_page = WebDriverWait(self.driver, 10).until(
        #     EC.presence_of_element_located((By.XPATH, "//*[@id='memoryDetail']"))
        # )
        # body = self.driver.find_element(By.TAG_NAME, "body")
        # body.send_keys(Keys.END)

        # 解析
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//*[@id='memoryDetail']/tbody/tr[last()]"))
        )
        mem_elements_list = self.driver.find_elements(By.XPATH, "//*[@id='memoryDetail']/tbody/tr")
        # 创建存放数据的列表
        names = []
        providers = []
        m_sns = []
        # 解析页面获取数据，将数据存入列表
        for mem_element in mem_elements_list:
            # 在每个tr元素下找到所有的e元素并点击
            opes = mem_element.find_elements(By.XPATH, ".//e")
            for ope in opes:
                ope.click()
            mem_names = mem_element.find_elements(By.XPATH, "./td[1]")
            for name in mem_names:
                names.append(name.text)
            mem_providers = mem_element.find_elements(By.XPATH, "./td[last()]")
            for provider in mem_providers:
                providers.append(provider.text)
        mem_sns = self.driver.find_elements(By.XPATH,
                                            "//*[@id='memoryDetail']/tbody/tr/td/table/tbody/tr[2]/td/div/div[2]")
        for mem_sn in mem_sns:
            m_sns.append(mem_sn.text.split(" ")[1])
        # print(names, providers, m_sns)
        # 同时遍历三个列表将数据添加到字典中
        for i, j, k in zip(names, providers, m_sns):
            if i.split("_")[0] == "CPU1":
                cpu1_mem[i.split("_")[2]] = {
                    "provider": j,
                    "sn": k
                }
                self.sn["cpu1_mem"] = cpu1_mem

            elif i.split("_")[0] == "CPU2":
                cpu2_mem[i.split("_")[2]] = {
                    "provider": j,
                    "sn": k
                }
                self.sn["cpu2_mem"] = cpu2_mem

    def get_main_card_sn(self):
        # 进入其他，打开主板详情页
        other_button = self.driver.find_element(By.XPATH, "//*[@id='app-tab']/div/ul/li[5]")
        other_button.click()
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, "//*[@id='others_board_info']/div/div/div[1]/div/div/div/ul/li/ul[1]/li[1]/span/a"))
        )
        ope = self.driver.find_element(By.XPATH,
                                       "//*[@id='others_board_info']/div/div/div[1]/div/div/div/ul/li/ul[1]/li[1]/span/a")
        ope.click()
        base_board = self.driver.find_element(By.XPATH,
                                              "//*[@id='others_board_info']/div/div/div[1]/div/div/div/ul/li/ul[1]/li[2]/ul/li/div/span")
        base_board.click()
        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='others-box']/div/div/div[2]/div[4]/div"))
        )
        self.sn["main_board_sn"] = self.driver.find_element(By.XPATH,
                                                            "//*[@id='others-box']/div/div/div[2]/div[4]/div").text.split(
            " ")[1]

    def get_cpu_info(self):
        # 进入处理器页
        cpu_button = self.driver.find_element(By.XPATH, "//*[@id='app-tab']/div/ul/li[2]")
        cpu_button.click()
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='processorDatabase']/tbody/tr[1]/td[4]"))
        )
        self.sn["cpu_type"] = self.driver.find_element(By.XPATH,
                                                       "//*[@id='processorDatabase']/tbody/tr[1]/td[4]").text + " CPU*2"

    def get_network_sn(self):
        # 进入pcie设备
        network_card = {}
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='app-tab']/div/ul/li[4]"))
        )
        pcie_button = self.driver.find_element(By.XPATH, "//*[@id='app-tab']/div/ul/li[4]")
        pcie_button.click()

        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, "//*[@id='pcieDevice']/div/div/div[1]/div/div/div/ul/li/ul/li[2]/ul/li[1]/div"))
        )
        nic1_ope = self.driver.find_element(By.XPATH,
                                            "//*[@id='pcieDevice']/div/div/div[1]/div/div/div/ul/li/ul/li[2]/ul/li[1]/div")
        nic1_ope.click()
        nic1_sn = self.driver.find_element(By.XPATH, "//*[@id='nic-box']/div[1]/div/div[2]/div[5]/div").text.split(" ")[
            1]
        network_card["card1"] = {
            "slot": "1",
            "sn": nic1_sn,
            "type": "NIC-ETH540F-LP-2P"
        }
        nic2_ope = self.driver.find_element(By.XPATH,
                                            "//*[@id='pcieDevice']/div/div/div[1]/div/div/div/ul/li/ul/li[2]/ul/li[2]/div/span")
        nic2_ope.click()
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='nic-box']/div[1]/div/div[2]/div[5]/div"))
        )
        nic2_sn = self.driver.find_element(By.XPATH, "//*[@id='nic-box']/div[1]/div/div[2]/div[5]/div").text.split(" ")[
            1]
        network_card["card2"] = {
            "slot": "16",
            "sn": nic2_sn,
            "type": "NIC-ETH540F-LP-2P"
        }
        self.sn["network_card"] = network_card

    def get_back_sn(self):
        back = {}
        # 进入存储管理
        storge_management = self.driver.find_element(By.XPATH,
                                                     "//*[@id='main']/div/div/div/div[2]/div/div[1]/ul/li[2]/a")
        storge_management.click()
        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//*[@id='storageinfo']/li[1]/ul[2]/li[1]/span/span"))
        )
        # 解析页面
        storge_list = self.driver.find_elements(By.XPATH, "//*[@id='storageinfo']/li[1]/ul[2]/li[2]/ul/li")
        # 创建数据存放的列表
        storge_numbers = []
        storge_types = []
        storge_sns = []
        storge_sizes = []
        # 继续解析子页面， 将数据存入例表中
        for storge_info in storge_list:
            storge_info.click()
            storge_number = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[1]/div[2]")
            storge_type = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[4]/div[2]")
            storge_sn = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[6]/div[2]")
            storge_size = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[9]/div[2]")
            storge_numbers.append(storge_number.text.split(" ")[-1])
            storge_types.append(storge_type.text)
            storge_sns.append(storge_sn.text)
            storge_sizes.append(storge_size.text.split(" ")[-1])
        # 遍历列表，组装字典，将字典添加到大字典中
        for i, j, k, l in zip(storge_numbers, storge_types, storge_sns, storge_sizes):
            # print(i, j, k)
            back["disk{}".format(i)] = {
                "number": i,
                "type": j + " " + l,
                "sn": k
            }
            self.sn["back"] = back

    def get_front_sn(self):
        front = {}
        ssd = {}
        # 进入前置硬盘列表
        front_disk_list = self.driver.find_element(By.XPATH, "//*[@id='storageinfo']/li[2]/span/a/span")
        front_disk_list.click()
        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//*[@id='storageinfo']/li[2]/ul[2]/li[1]/span/span"))
        )
        # 解析页面
        storge_list = self.driver.find_elements(By.XPATH, "//*[@id='storageinfo']/li[2]/ul[2]/li[2]/ul/li")
        # print(storge_list)
        # 创建数据存放的列表
        storge_numbers = []
        storge_types = []
        storge_sns = []
        storge_sizes = []
        storge_attributes = []
        # 继续解析子页面， 将数据存入例表中
        for storge_info in storge_list:
            storge_info.click()
            storge_number = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[1]/div[2]")
            storge_type = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[4]/div[2]")
            storge_sn = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[6]/div[2]")
            storge_size = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[9]/div[2]")
            storge_attribute = self.driver.find_element(By.XPATH, "//*[@id='storagePhysicalDetailInfo']/div[8]/div[2]")
            storge_numbers.append(storge_number.text.split(" ")[-1])
            storge_types.append(storge_type.text)
            storge_sns.append(storge_sn.text)
            storge_sizes.append(storge_size.text.split(" ")[-1])
            storge_attributes.append(storge_attribute.text.split(" ")[-1])
        # print(storge_attributes)
        for i, j, k, l, h in zip(storge_numbers, storge_types, storge_sns, storge_sizes, storge_attributes):
            if h == "HDD":
                front["disk{}".format(i)] = {
                    "number": i,
                    "type": j + " " + l,
                    "sn": k
                }
                self.sn["front"] = front
            elif h == "SSD":
                ssd["disk{}".format(i)] = {
                    "number": i,
                    "type": j + " " + l,
                    "sn": k
                }
                self.sn["ssd"] = ssd

    def get_hba_sn(self):
        raid_card = {}
        # 点击hba card 1
        hba_card1 = self.driver.find_element(By.XPATH, "//*[@id='storageinfo']/li[1]/span/span[1]")
        hba_card1.click()
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//*[@id='storageCardDetailInfo']/div[2]/div[1]"))
        )
        type1 = self.driver.find_element(By.XPATH, "//*[@id='storageCardDetailInfo']/div[2]/div[2]")
        # print(type1)
        sn1 = self.driver.find_element(By.XPATH, "//*[@id='storageCardDetailInfo']/div[4]/div[2]")
        raid_card["card1"] = {
            "type": type1.text,
            "sn": sn1.text
        }
        # 点击hba card 2
        hba_card2 = self.driver.find_element(By.XPATH, "//*[@id='storageinfo']/li[2]/span/span[1]")
        hba_card2.click()
        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='storageCardDetailInfo']/div[2]/div[2]"))
        )
        type2 = self.driver.find_element(By.XPATH, "//*[@id='storageCardDetailInfo']/div[2]/div[2]")
        sn2 = self.driver.find_element(By.XPATH, "//*[@id='storageCardDetailInfo']/div[4]/div[2]")
        raid_card["card2"] = {
            "type": type2.text,
            "sn": sn2.text
        }
        self.sn["raid_card"] = raid_card

    def get_power_sn(self):
        power = {}
        # 进入电源管理
        power_button = self.driver.find_element(By.XPATH, "//*[@id='main']/div/div/div/div[2]/div/div[1]/ul/li[3]/a")
        power_button.click()
        # 等待页面加载
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='app-tab']/div/ul/li[2]"))
        )
        # 进入电源信息详情页
        power_info = self.driver.find_element(By.XPATH, "//*[@id='app-tab']/div/ul/li[2]")
        power_info.click()
        # 等到页面加载
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//*[@id='powerList']/div[1]/div[2]/div[5]/div[2]"))
        )
        # 获取电源sn
        power1_slot = self.driver.find_element(By.XPATH, "//*[@id='powerList']/div[1]/div[2]/div[2]/div[2]").text
        power1_sn = self.driver.find_element(By.XPATH, "//*[@id='powerList']/div[1]/div[2]/div[5]/div[2]").text
        power["power1"] = {
            "slot": power1_slot,
            "sn": power1_sn
        }
        power2_slot = self.driver.find_element(By.XPATH, "//*[@id='powerList']/div[2]/div[2]/div[2]/div[2]").text
        power2_sn = self.driver.find_element(By.XPATH, "//*[@id='powerList']/div[2]/div[2]/div[5]/div[2]").text
        power["power2"] = {
            "slot": power2_slot,
            "sn": power2_sn
        }
        self.sn["power"] = power

    def close(self):
        self.driver.close()

    def write_to_file(self, sn_dict, json_file_path):
        with open(json_file_path, 'w', encoding='utf8') as f:
            json.dump(sn_dict, f, indent=4)

    def get_sn(self):

        self.login()
        self.get_server_sn()
        self.get_mem_sn()
        self.get_main_card_sn()
        self.get_cpu_info()
        self.get_network_sn()
        self.get_back_sn()
        self.get_front_sn()
        self.get_hba_sn()
        self.get_power_sn()
        sleep(2)
        self.close()
        self.write_to_file(self.sn, self.path)
        print(self.sn)


if __name__ == '__main__':
    url = "http://10.223.10.241/"
    username = "admin"
    password = "Iamadm1n!!"
    path = "sn-new.json"
    SN = AcquireSN(url, username, password, path)
    SN.get_sn()
